<?php

namespace app\api\service;

use addons\xyb\XypHelper;
use app\api\controller\xyb\OrderReceive ;
use app\api\model\xyb\Order;
use app\api\model\xyb\OrderComplaint;
use app\api\model\xyb\Profit;
use app\api\model\xyb\Server;
use app\api\model\xyb\UserReceiveApply;
use app\api\model\xyb\Wallets;
use app\common\model\xyb\AdminBelong;

class OrdersService
{

    public static function confirmCompleteOrders($orders){
        if(!$orders){
            return false;
        }
        $time = time();
        $order_model = (new Order());
        if(!$agent_id = (isset($orders['agent_id'])?intval($orders['agent_id']):0)){
            return 1;
        }
        if(!$order_type = (isset($orders['type'])?intval($orders['type']):0)){
            return false;
        }
        if(!$receive_id = (isset($orders['receive_id'])?intval($orders['receive_id']):0)){
            return false;
        }
        // 获取订单类型文本描述
        $server_name = $order_model->getTypeTextName($order_type);

        /*获取代理服务信息*/
        $distribution_rate = self::CalculateOrdersDistributionRate($orders->price, $agent_id, $server_name);
       /*更新平台收益*/
        if(!Wallets::saveUsersWalletIncome(1,3, $distribution_rate['platform_amount'])){
            return false;
        }
        /*更新代理收益*/
        if(!Wallets::saveUsersWalletIncome($agent_id,2, $distribution_rate['agent_amount'])){
            return false;
        }
        /*更新跑腿员收益*/
        if(!Wallets::saveUsersWalletIncome($receive_id,1, $distribution_rate['receive_amount'])){
            return false;
        }
        if(!Profit::saveProfit($orders, $distribution_rate)){
            return false;
        }
        /*修改订单状态*/
        $res = $order_model->save(
            ['status'=>3, 'complete_time'=>$time, 'expiretime'=>$time + 86400],
            ['id'=>$orders['id'], 'status' => 7]
        );
        if(!$res){
            return false;
        }
        return true;
    }

    /**
     * 评价订单
     *
     * 本函数用于处理订单的评价信息，包括服务速度和服务态度的评价，并更新订单状态和相关收益记录
     * 同时，根据接收者的评价记录，更新接收者的评价分数
     *
     * @param int $order_id 订单ID
     * @param int $receive_id 接收者ID
     * @param int $speed 服务速度评分
     * @param int $attitude 服务态度评分
     *
     * @return bool 返回评价处理结果，true表示成功，false表示失败
     */
    public static function evaluateOrders($order_id, $receive_id, $speed, $attitude){
        // 计算总评价分数，保留两位小数
        $total = sprintf('%.2f', ((((int)$speed) + ((int)$attitude)) / 2));

        $json = ['speed'=>$speed, 'attitude'=>$attitude,'total' => $total];
        /*修改订单状态*/
        // 更新订单的评价信息和状态，只更新状态为3的订单
        $update =  ['evaluate'=>$total, 'evaluate_time'=>time()];
        $res = Order::where( ['id'=>$order_id,'status' => 3])->update($update); //,
        if(!$res){
            return false;
        }
        \app\api\model\xyb\OrderReceive::where('order_id', $order_id)->update([
            'evaluate'      => XypHelper::formatArrayToString($json),
            'updatetime'    => time()
        ]);
        // 更新收益记录的评价分数和更新时间
        $res = Profit::where(['order_id'=>$order_id, 'receive_id'=>$receive_id])->update(['evaluate' => $total, 'updatetime'=>time()]);
        if(!$res){
            return false;
        }
        // 初始化接收者评价分数为5分
        $receive_evaluate = 5;
        // 获取接收者已评价的订单数量
        $receive_order_count = (int)Profit::where('receive_id', $receive_id)->where('evaluate','>', 0)->count('id');
        // 获取接收者总的评价分数
        $receive_order_evaluate = (float)Profit::where('receive_id', $receive_id)->sum('evaluate');
        // 如果接收者有评价记录，则计算平均评价分数
        if($receive_order_count){
            $receive_evaluate = sprintf('%.2f', ($receive_order_evaluate / $receive_order_count));
        }
        // 更新接收者的评价分数
        UserReceiveApply::where('user_id', $receive_id)->update(['evaluate'=>$receive_evaluate, 'updatetime'=> time()]);
        return true;
    }


    public static function complaintOrders($orders, $content, $picture){
        $complaint = [
            'order_id'      => $orders->id,
            'order_no'      => XypHelper::xyb_get_order_no(),
            'agent_id'      => $orders->agent_id,
            'user_id'       => $orders->user_id,
            'receive_id'    => $orders->receive_id,
            'type'          => $orders->type,
            'status'        => 0,
            'createtime'    => time(),
            'content'       => $content,
            'picture'       => $picture,
        ];

        OrderComplaint::create($complaint);
    }

    /**
     * 计算订单收入分配
     *
     * 该方法根据订单信息计算平台、代理和接收方各自的收入份额
     * 它首先确定订单的类型和相关信息，然后根据预定义的比例分配总收入
     * 如果在分配过程中出现偏差，该方法会确保将偏差补给接收方
     *
     * @param array $data 订单数据，包括订单类型和ID
     * @return array 包含总收入、平台收入、代理收入和接收方收入的数组
     */
    public static function CalculateOrdersRevenue($data)
    {
        // 获取订单类型文本描述
        $server_name = (new Order())->getTypeTextAttr($data['type'], $data);

        // 获取特定订单对象
        $orderObj = (new Order())->get($data['id']);

        // 获取代理服务项目信息
        $server_info = self::getAgentServiceItemInfo($orderObj->agent_id, $server_name);

        // 初始化总收入
        $total_fee = (float)$orderObj['price'];

        // 计算平台收益
        $platform_profit = (float)(bcmul($orderObj['price'], $server_info['platform_profit'], 2));

        // 计算代理收益
        $agent_profit = (float)(bcmul($orderObj['price'], $server_info['agent_profit'], 2));

        // 计算接收方收益
        $receive_profit = (float)(bcmul($orderObj['price'], $server_info['receive_profit'], 2));

        /*计算偏差；于数补给跑腿员*/
        if($reduce_agent = (float)($total_fee - ($platform_profit + $agent_profit + $receive_profit))){
            $receive_profit += $reduce_agent;
        }

        // 返回收入分配结果
        return [
            'total_amount'      => $total_fee,
            'platform_amount'   => (float)sprintf("%.2f", $platform_profit),
            'agent_amount'      => (float)sprintf("%.2f",$agent_profit),
            'receive_amount'    => (float)sprintf("%.2f",$receive_profit),
        ];
    }

    /**
     * 获取代理服务项目的相关信息
     *
     * 此函数用于根据代理ID和服务器名称获取代理服务项目的利润分配情况
     * 它会查询数据库中的Server表，提取出平台利润、代理利润和接收利润，
     * 并将这些利润信息以数组形式返回，且每个利润值都转换为百分比形式
     *
     * @param int $agent_id 代理ID，用于标识特定的代理
     * @param string $server_name 服务器名称，用于标识特定的服务项目
     *
     * @return array 包含平台利润、代理利润和接收利润的数组，每个利润值都以百分比形式表示
     */
    public static function getAgentServiceItemInfo($agent_id, $server_name){
        // 定义查询条件，用于精确查找特定代理和服务器的记录
        if($server_name == '帮我送'){
            $server_name = '校园跑腿';
        }
        if($server_name == '取快递'){
            $server_name = '快递代取';
        }
        $condition = ['agent_id' => $agent_id, 'server_name' => $server_name];
        // 指定需要查询的字段，即平台利润、代理利润和接收利润
        $field = 'agent_profit,receive_profit,platform_profit';

        // 创建Server实例，根据条件查询指定字段，并获取第一条记录
        $server_info = (new Server())->where($condition)->field($field)->find();

        // 返回利润信息，每个利润值都除以100转换为百分比形式，并确保其为浮点数类型
        return [
            'platform_profit'   => ((float)$server_info->platform_profit) / 100,
            'agent_profit'      => ((float)$server_info->agent_profit) / 100,
            'receive_profit'    => ((float)$server_info->receive_profit) / 100,
        ];
    }

    /**
     * 获取代理服务的默认接收ID
     *
     * 此方法用于根据代理ID和类型键获取对应的默认接收ID它首先将类型键转换为类型文本名称，
     * 然后使用代理ID和类型文本名称查询Server模型，以获取默认接收ID
     *
     * @param int $agent_id 代理的ID，用于查询Server模型
     * @param mixed $type_key 类型键，需要转换为类型文本名称以用于查询
     *
     * @return int 默认接收ID，如果查询不到则返回0
     */
    public static function getAgentServiceDefaultReceiveId($agent_id, $type_key)
    {
        // 将类型键转换为类型文本名称
        $type_text = (new Order())->getTypeTextName($type_key);

        // 构造查询条件，包括代理ID和服务器名称（由类型文本名称表示）
        $condition = ['agent_id' => $agent_id, 'server_name' => $type_text];

        // 查询并返回默认接收ID，如果没有找到匹配的记录，则返回0
        return (int)(new Server())->where($condition)->value('default_receive_id');
    }

    /**
     * 获取代理服务的默认接收ID
     *
     * 此方法用于根据代理ID和类型键获取对应的默认接收ID它首先将类型键转换为类型文本名称，
     * 然后使用代理ID和类型文本名称查询Server模型，以获取默认接收ID
     *
     * @param int $agent_id 代理的ID，用于查询Server模型
     * @param string $key 类型键，需要转换为类型文本名称以用于查询
     *
     * @return int 默认接收ID，如果查询不到则返回0
     */
    public static function getAgentAdminBelongIspickCode($agent_id)
    {


        // 构造查询条件，包括代理ID和服务器名称（由类型文本名称表示）
        $condition = ['admin_id' => $agent_id];

        // 查询并返回默认接收ID，如果没有找到匹配的记录，则返回0
        return ((int)(new AdminBelong())->where($condition)->value('pick_code')) === 1;
    }

    /*
     *  *  0：待付款，
     *  1：已付款 接单员可接单；
     *  2：已接单 接单员接单成功，待取件，
     *  8：已取件（确认收件）待送达；
     *  7：已送达 待发布人确认完成；
     *  3：已完成 发布人完成，金额分成，
     *  4：已取消；，
     *  6：已退款；
     * */
    /**
     * 根据订单状态码返回订单状态描述
     *
     * 此函数用于将订单的状态码映射到人类可读的订单状态描述，以便于在用户界面或其他需要的地方使用
     * 它接受一个整数状态码作为输入，并返回相应的订单状态字符串如果输入的状态码不在预定义的范围内，
     * 函数将返回一个空字符串
     *
     * @param int $status 订单状态码，表示订单的当前状态
     * @return string 订单状态的描述，如果状态码未知则返回空字符串
     */
    public static function formatOrdersStatus($status){
        switch ($status){
            case 0:
                return '待付款';
            case 1:
                return '已付款，待接单';
            case 2:
                return '已接单，取件中';
            case 3:
                return '已完成';
            case 4:
                return '已取消';
            case 5:
                return '';
            case 6:
                return '已退款';
            case 7:
                return '已完成，待确认';
            case 8:
                return '已取件，待送达';
            default:
                return '';
        }
    }


    public static function CalculateOrdersDistributionRate($total_fee, $agent_id, $server_name)
    {
        // 获取代理服务项目信息
        $server_info = self::getAgentServiceItemInfo($agent_id, $server_name);

        // 计算平台收益
        $platform_profit = (float)(bcmul($total_fee, $server_info['platform_profit'], 2));

        // 计算代理收益
        $agent_profit = (float)(bcmul($total_fee, $server_info['agent_profit'], 2));

        // 计算接收方收益
        $receive_profit = (float)(bcmul($total_fee, $server_info['receive_profit'], 2));

        /*计算偏差；于数补给跑腿员*/
        if($reduce_agent = (float)($total_fee - ($platform_profit + $agent_profit + $receive_profit))){
            $receive_profit += $reduce_agent;
        }
        // 返回收入分配结果
        return [
            'total_amount'      => $total_fee,
            'platform_amount'   => (float)sprintf("%.2f", $platform_profit),
            'agent_amount'      => (float)sprintf("%.2f",$agent_profit),
            'receive_amount'    => (float)sprintf("%.2f",$receive_profit),
        ];
    }

    /**
     * 计算订单收入分配
     *
     * 该方法根据订单信息计算平台、代理和接收方各自的收入份额
     * 它首先确定订单的类型和相关信息，然后根据预定义的比例分配总收入
     * 如果在分配过程中出现偏差，该方法会确保将偏差补给接收方
     *
     * @param float $total_fee 订单数据，包括订单类型和ID
     * @param int $agent_id 订单数据，包括订单类型和ID
     * @param string $server_name 订单数据，包括订单类型和ID
     * @return array 包含总收入、平台收入、代理收入和接收方收入的数组
     */
    public static function CalculateOrdersRevenueProportion($total_fee, $agent_id, $server_type)
    {
        $server_name = Order::getTypeNameTextName($server_type);
        // 获取代理服务项目信息
        $server_info = self::getAgentServiceItemInfo($agent_id, $server_name);

        // 计算平台收益
        $platform_profit = (float)(bcmul($total_fee, $server_info['platform_profit'], 2));

        // 计算代理收益
        $agent_profit = (float)(bcmul($total_fee, $server_info['agent_profit'], 2));

        // 计算接收方收益
        $receive_profit = (float)(bcmul($total_fee, $server_info['receive_profit'], 2));

        /*计算偏差；于数补给跑腿员*/
        if($reduce_agent = (float)($total_fee - ($platform_profit + $agent_profit + $receive_profit))){
            $receive_profit += $reduce_agent;
        }

        // 返回收入分配结果
        return [
            'total_amount'      => $total_fee,
            'platform_amount'   => (float)sprintf("%.2f", $platform_profit),
            'agent_amount'      => (float)sprintf("%.2f", $agent_profit),
            'receive_amount'    => (float)sprintf("%.2f", $receive_profit),
        ];
    }


}